local gui = Instance.new("ScreenGui") gui.Parent = owner.PlayerGui local function isDescendantOfCharacter(instance) local p = instance.Parent repeat if p:FindFirstChildOfClass("Humanoid") then return true end p = p.Parent until not p return false end local build = Instance.new("Tool") build.Name = "Build" build.Grip = CFrame.new(0, 0, -0.5, 0, 0, 1, 1, 0, 0, 0, 1, 0) build.CanBeDropped = false local buildHandle = Instance.new("Part") buildHandle.Name = "Handle" buildHandle.Size = Vector3.new(1, 0.8, 3) buildHandle.Parent = build local buildMesh = Instance.new("SpecialMesh") buildMesh.Scale = Vector3.new(1.2, 1.2, 1.2) buildMesh.MeshType = Enum.MeshType.FileMesh buildMesh.TextureId = "rbxassetid://16198294" buildMesh.MeshId = "rbxassetid://16198309" buildMesh.Parent = buildHandle local remoteBuild = Instance.new("RemoteEvent") remoteBuild.Name = "Build" remoteBuild.Parent = gui remoteBuild.OnServerEvent:Connect(function(player, size, cframe, target) if player ~= owner then return end if not target or target.Parent == nil then return end local part = Instance.new("Part") part.BrickColor = BrickColor.new("Cork") part.Material = Enum.Material.WoodPlanks part.Size = size part.CFrame = target.CFrame:ToWorldSpace(cframe) local weld = Instance.new("WeldConstraint") weld.Part0 = part weld.Part1 = target weld.Parent = part part.Parent = workspace end) local remoteDestroy = Instance.new("RemoteEvent") remoteDestroy.Name = "Destroy" remoteDestroy.Parent = gui remoteDestroy.OnServerEvent:Connect(function(player, target) if player ~= owner then return end if target.Locked or isDescendantOfCharacter(target) then return end target:Destroy() end) local function onCharacterAdded(character) local backpack = owner:WaitForChild("Backpack") local newBuild = build:Clone() newBuild.Parent = backpack end owner.CharacterAdded:Connect(onCharacterAdded) onCharacterAdded(owner.Character) local localScript = NLS([=[local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local Players = game:GetService("Players") local localPlayer = Players.LocalPlayer local VEC3_HALF = Vector3.new(0.5, 0.5, 0.5) local axes = { Vector3.xAxis, Vector3.yAxis, Vector3.zAxis } local remoteBuild = script.Parent:WaitForChild("Build") local remoteDestroy = script.Parent:WaitForChild("Destroy") local buildTool local toolConns = {} local rcParams = RaycastParams.new() rcParams.FilterType = Enum.RaycastFilterType.Blacklist rcParams.FilterDescendantsInstances = {Players.LocalPlayer.Character} rcParams.IgnoreWater = true local cursorPart = Instance.new("Part") cursorPart.Size = Vector3.one cursorPart.Anchored = true cursorPart.CanTouch = false cursorPart.CanCollide = false cursorPart.CanQuery = false cursorPart.CastShadow = false cursorPart.Color = Color3.new(1, 1, 1) cursorPart.Transparency = 0.75 cursorPart.Material = Enum.Material.Neon local planeIndicator = Instance.new("Part") planeIndicator.Size = Vector3.one planeIndicator.Anchored = true planeIndicator.CanTouch = false planeIndicator.CanCollide = false planeIndicator.CanQuery = false planeIndicator.CastShadow = false planeIndicator.Color = Color3.new(0.7, 0.7, 0.7) planeIndicator.Material = Enum.Material.Neon local planeIndicatorMesh = Instance.new("SpecialMesh") planeIndicatorMesh.MeshType = Enum.MeshType.Brick planeIndicatorMesh.Scale = Vector3.new(0, 1, 1) planeIndicatorMesh.Parent = planeIndicator for _, side in pairs(Enum.NormalId:GetEnumItems()) do local texture = Instance.new("Texture") texture.Face = side texture.Texture = "rbxassetid://41116694" texture.Transparency = 0.75 texture.StudsPerTileU = 1 texture.StudsPerTileV = 1 texture.Parent = cursorPart end local dragStart = nil local dragPart = nil local isGrabbing = false local axIdx = 2 local axis = axes[2] local function getRelativeGrid(part) if part:IsA("Terrain") then return CFrame.new() end return part.CFrame * CFrame.new(part.Size*-0.5) end local function floorVec3(vec) return Vector3.new(math.floor(vec.X), math.floor(vec.Y), math.floor(vec.Z)) end local function absVector3(vec) return Vector3.new(math.abs(vec.X), math.abs(vec.Y), math.abs(vec.Z)) end local function intersectRayPlane(ray, planeCenter, planeNormal) local denom = planeNormal:Dot(ray.Direction.Unit) if math.abs(denom) > 0.0001 then local diff = planeCenter - ray.Origin local t = diff:Dot(planeNormal) / denom if t > 0 then return ray.Origin + ray.Direction.Unit*t else return nil end else return nil end end local function grab() local camera = workspace.CurrentCamera if not camera then return end local mPos = UserInputService:GetMouseLocation() local mRay = camera:ViewportPointToRay(mPos.X, mPos.Y) local rcResult = workspace:Raycast(mRay.Origin, mRay.Direction * 100, rcParams) if rcResult then local relGrid = getRelativeGrid(rcResult.Instance) local relPoint = relGrid:PointToObjectSpace(rcResult.Position) local relNormal = relGrid:VectorToObjectSpace(rcResult.Normal) dragPart = rcResult.Instance dragStart = floorVec3(relPoint + (relNormal*1e-5)) isGrabbing = true end end local function ungrab() if not isGrabbing then return end remoteBuild:FireServer(cursorPart.Size, dragPart.CFrame:ToObjectSpace(cursorPart.CFrame), dragPart) isGrabbing = false cursorPart.Size = Vector3.one end local function onCharacterAdded(character) for _, conn in pairs(toolConns) do conn:Disconnect() end buildTool = localPlayer.Backpack:WaitForChild("Build") assert(buildTool:IsA("Tool")) toolConns = { buildTool.Activated:Connect(function() grab() end), buildTool.Deactivated:Connect(function() ungrab() end), buildTool.Equipped:Connect(function() cursorPart.Parent = workspace.CurrentCamera planeIndicator.Parent = workspace.CurrentCamera end), buildTool.Unequipped:Connect(function() cursorPart.Parent = nil planeIndicator.Parent = nil end) } end UserInputService.InputBegan:Connect(function(input, gameProcessedEvent) if gameProcessedEvent then return end if buildTool and buildTool.Parent == localPlayer.Character then if input.KeyCode == Enum.KeyCode.BackSlash or ( input.UserInputType == Enum.UserInputType.MouseButton2 and UserInputService.MouseBehavior == Enum.MouseBehavior.LockCenter ) then local camera = workspace.CurrentCamera if not camera then return end local mPos = UserInputService:GetMouseLocation() local mRay = camera:ViewportPointToRay(mPos.X, mPos.Y) local rcResult = workspace:Raycast(mRay.Origin, mRay.Direction * 100, rcParams) if rcResult then remoteDestroy:FireServer(rcResult.Instance) end end if input.KeyCode == Enum.KeyCode.Q then axIdx = (axIdx%3) + 1 axis = axes[axIdx] end end end) UserInputService.InputEnded:Connect(function(input, gameProcessedEvent) if gameProcessedEvent then return end if input.UserInputType == Enum.UserInputType.MouseButton1 then ungrab() end end) Players.LocalPlayer.CharacterAdded:Connect(function(character) onCharacterAdded(character) rcParams.FilterDescendantsInstances = {character} end) RunService.RenderStepped:Connect(function(dt) local camera = workspace.CurrentCamera if not camera then return end local mPos = UserInputService:GetMouseLocation() local mRay = camera:ViewportPointToRay(mPos.X, mPos.Y) local rcResult = workspace:Raycast(mRay.Origin, mRay.Direction * 100, rcParams) local grid = getRelativeGrid((isGrabbing and dragPart) or (rcResult and rcResult.Instance) or workspace.Terrain) local planeNormal, relativeAxis local maxDot = -math.huge for _, normalId in pairs(Enum.NormalId:GetEnumItems()) do local newRelativeNormal = Vector3.FromNormalId(normalId) local newPlaneNormal = grid:VectorToWorldSpace(newRelativeNormal) local newDot = newPlaneNormal:Dot(axis) if newDot > maxDot then planeNormal = newPlaneNormal relativeAxis = absVector3(newRelativeNormal) maxDot = newDot end end assert(planeNormal) local planeIndicatorCenter if isGrabbing then local globalCF = grid:ToWorldSpace(CFrame.new(dragStart)) local worldDragEnd = intersectRayPlane(mRay.Unit, globalCF.Position, planeNormal) if worldDragEnd then local dragEnd = (grid:PointToObjectSpace(worldDragEnd + planeNormal)*(Vector3.one - relativeAxis)) + (dragStart*relativeAxis) local pointA = floorVec3(dragEnd:Min(dragStart)) local pointB = floorVec3((dragEnd + Vector3.one):Max(dragStart+ Vector3.one)) if dragEnd then cursorPart.CFrame = grid:ToWorldSpace(CFrame.new(pointA:Lerp(pointB, 0.5))) cursorPart.Size = pointB - pointA end planeIndicatorCenter = grid:PointToWorldSpace(floorVec3(grid:PointToObjectSpace(worldDragEnd)) + VEC3_HALF) end else if rcResult then local relGrid = getRelativeGrid(rcResult.Instance) local relPoint = relGrid:PointToObjectSpace(rcResult.Position) local relNormal = relGrid:VectorToObjectSpace(rcResult.Normal) cursorPart.CFrame = relGrid * CFrame.new(floorVec3(relPoint + (relNormal*1e-5)) + VEC3_HALF) end end planeIndicatorCenter = planeIndicatorCenter or cursorPart.CFrame.Position planeIndicator.CFrame = CFrame.fromMatrix( planeIndicatorCenter, planeNormal, cursorPart.CFrame.YVector:Dot(planeNormal) < cursorPart.CFrame.ZVector:Dot(planeNormal) and cursorPart.CFrame.YVector or cursorPart.CFrame.ZVector ) end) onCharacterAdded(localPlayer.Character)]=], gui)